<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <title>Symbolic Constants</title>
</head>

<body>
  <h1>Symbolic Constants</h1>

  <h2>Overview</h2>

  <p>It is often useful to define names which will be treated as
  constants.  <code class="API">twisted.python.constants</code> provides APIs
  for defining such symbolic constants with minimal overhead and some useful
  features beyond those afforded by the common Python idioms for this task.</p>

  <p>This document will explain how to use these APIs and what circumstances
  they might be helpful in.</p>

  <h2>Constant Names</h2>

  <p>Constants which have no value apart from their name and identity can be
  defined by subclassing <code class="API" base="twisted.python.constants">Names</code>.
  Consider this example, in which some HTTP request method constants are defined.</p>

  <pre class="python">
from twisted.python.constants import NamedConstant, Names
class METHOD(Names):
    """
    Constants representing various HTTP request methods.
    """
    GET = NamedConstant()
    PUT = NamedConstant()
    POST = NamedConstant()
    DELETE = NamedConstant()
  </pre>

  <p>Only direct subclasses of <code>Names</code> are supported (i.e., you
  cannot subclass <code>METHOD</code> to add new constants the collection).</p>

  <p>Given this definition, constants can be looked up by name using attribute
  access on the <code>METHOD</code> object:</p>

  <pre class="shell">
>>> METHOD.GET
&lt;METHOD=GET>
>>> METHOD.PUT
&lt;METHOD=PUT>
>>>
  </pre>

  <p>If it's necessary to look up constants based on user input of some sort, a
  safe way to do it is using <code>lookupByName</code>:</p>

  <pre class="shell">
>>> METHOD.lookupByName('GET')
&lt;METHOD=GET>
>>> METHOD.lookupByName('__doc__')
Traceback (most recent call last):
  File "&lt;stdin>", line 1, in &lt;module>
  File "twisted/python/constants.py", line 145, in lookupByName
    raise ValueError(name)
ValueError: __doc__
>>>
  </pre>

  <p>As demonstrated, it is safe because any name not associated with a constant
  (even those special names initialized by Python itself) will result
  in <code>ValueError</code> being raised, not some other object not intended to
  be used the way the constants are used.</p>

  <p>The constants can also be enumerated using the <code>iterconstants</code>
  method.</p>

  <pre class="shell">
>>> list(METHOD.iterconstants())
[&lt;METHOD=GET>, &lt;METHOD=PUT>, &lt;METHOD=POST>, &lt;METHOD=DELETE>]
>>>
  </pre>

  <p>And constants can also be compared, either for equality or identity:</p>

  <pre class="shell">
>>> METHOD.GET is METHOD.GET
True
>>> METHOD.GET == METHOD.GET
True
>>> METHOD.GET is METHOD.PUT
False
>>> METHOD.GET == METHOD.PUT
False
>>>
  </pre>

  <p>Custom functionality can also be associated with constants defined this
  way.  A subclass of <code>Names</code> may define class methods to implement
  such functionality.  Consider this redefinition of <code>METHOD</code>:</p>

  <pre class="python">
from twisted.python.constants import NamedConstant, Names
class METHOD(Names):
    """
    Constants representing various HTTP request methods.
    """
    GET = NamedConstant()
    PUT = NamedConstant()
    POST = NamedConstant()
    DELETE = NamedConstant()

    @classmethod
    def isIdempotent(cls, method):
        """
        Return True if the given method is side-effect free, False otherwise.
        """
        return method is cls.GET
  </pre>

  <p>This functionality can be used as any class methods are used:</p>

  <pre class="shell">
>>> METHOD.isIdempotent(METHOD.GET)
True
>>> METHOD.isIdempotent(METHOD.POST)
False
>>>
  </pre>

  <h2>Constants With Values</h2>

  <p>Constants with a particular associated value are supported by
  the <code class="API" base="twisted.python.constants">Values</code> base
  class.  Consider this example, in which some HTTP status code constants are
  defined.
  </p>

  <pre class="python">
from twisted.python.constants import ValueConstant, Values
class STATUS(Values):
    """
    Constants representing various HTTP status codes.
    """
    OK = ValueConstant("200")
    FOUND = ValueConstant("302")
    NOT_FOUND = ValueConstant("404")
  </pre>

  <p>As with <code>Names</code>, constants are accessed as attributes of the
  class object:</p>

  <pre class="shell">
>>> STATUS.OK
&lt;STATUS=OK>
>>> STATUS.FOUND
&lt;STATUS=FOUND>
>>>
  </pre>

  <p>Additionally, the values of the constants can be accessed using
  the <code>value</code> attribute of one these objects:</p>

  <pre class="shell">
>>> STATUS.OK.value
'200'
>>>
  </pre>

  <p>And as with <code>Names</code>, constants can be looked up by name:</p>

  <pre class="shell">
>>> STATUS.lookupByName('NOT_FOUND')
&lt;STATUS=NOT_FOUND>
>>>
  </pre>

  <p>Constants on a <code>Values</code> subclass can also be looked up by
  value:</p>

  <pre class="shell">
>>> STATUS.lookupByValue('404')
&lt;STATUS=NOT_FOUND>
>>> STATUS.lookupByValue('500')
Traceback (most recent call last):
  File "&lt;stdin>", line 1, in &lt;module>
  File "twisted/python/constants.py", line 244, in lookupByValue
      raise ValueError(value)
ValueError: 500
>>>
  </pre>

  <p>Multiple constants may have the same value.  If they do,
  <code>lookupByValue</code> will find the one which is defined first.</p>

  <p>Iteration is also supported:</p>

  <pre class="shell">
>>> list(STATUS.iterconstants())
[&lt;STATUS=OK>, &lt;STATUS=FOUND>, &lt;STATUS=NOT_FOUND>]
>>>
  </pre>

  <p>And constants can be compared for equality and identity:</p>

  <pre class="shell">
>>> STATUS.OK == STATUS.OK
True
>>> STATUS.OK is STATUS.OK
True
>>> STATUS.OK == STATUS.OK
True
>>> STATUS.OK is STATUS.NOT_FOUND
False
>>> STATUS.OK == STATUS.NOT_FOUND
False
>>>
  </pre>

  <p>And, as with <code>Names</code>, a subclass of <code>Values</code> can
  define methods:</p>

  <pre class="python">
from twisted.python.constants import ValueConstant, Values
class STATUS(Values):
    """
    Constants representing various HTTP status codes.
    """
    OK = ValueConstant("200")
    NO_CONTENT = ValueConstant("204")
    NOT_MODIFIED = ValueConstant("304")
    NOT_FOUND = ValueConstant("404")

    @classmethod
    def hasBody(cls, status):
        """
        Return True if the given status is associated with a response body,
        False otherwise.
        """
        return status in (cls.NO_CONTENT, cls.NOT_MODIFIED)
  </pre>

  <p>This functionality can be used as any class methods are used:</p>

  <pre class="shell">
>>> STATUS.hasBody(STATUS.OK)
True
>>> STATUS.hasBody(STATUS.NO_CONTENT)
False
>>>
  </pre>

  <h2>Constants As Flags</h2>

  <p>Integers are often used as a simple set for constants.  The values for
  these constants are assigned as powers of two so that bits in the integer can
  be set to represent them.  Individual bits are often called <em>flags</em>.
  <code class="API" base="twisted.python.constants">Flags</code> supports this
  use-case, including allowing constants with particular bits to be set, for
  interoperability with other tools.</p>

  <p>POSIX filesystem access control is traditionally done using a bitvector
  defining which users and groups may perform which operations on a file.  This
  state might be represented using <code>Flags</code> as follows:</p>

  <pre class="python">
from twisted.python.constants import FlagConstant, Flags
class Permission(Flags):
    """
    Constants representing user, group, and other access bits for reading,
    writing, and execution.
    """
    OTHER_EXECUTE = FlagConstant()
    OTHER_WRITE = FlagConstant()
    OTHER_READ = FlagConstant()
    GROUP_EXECUTE = FlagConstant()
    GROUP_WRITE = FlagConstant()
    GROUP_READ = FlagConstant()
    USER_EXECUTE = FlagConstant()
    USER_WRITE = FlagConstant()
    USER_READ = FlagConstant()
  </pre>

  <p>
    As for the previous types of constants, these can be accessed as attributes
    of the class object:
  </p>

  <pre class="shell">
>>> Permission.USER_READ
&lt;Permission=USER_READ>
>>> Permission.USER_WRITE
&lt;Permission=USER_WRITE>
>>> Permission.USER_EXECUTE
&lt;Permission=USER_EXECUTE>
>>>
  </pre>

  <p>These constant objects also have a <code>value</code> attribute giving
  their integer value:</p>

  <pre class="shell">
>>> Permission.USER_READ.value
256
>>>
  </pre>

  <p>And these constants can be looked up by name or value:</p>

  <pre class="shell">
>>> Permission.lookupByName('USER_READ') is Permission.USER_READ
True
>>> Permission.lookupByValue(256) is Permission.USER_READ
True
>>>
  </pre>

  <p>Constants can also be combined using the logical operators <code>&amp;</code>
  (<em>and</em>), <code>|</code> (<em>or</em>), and <code>^</code>
  (<em>exclusive or</em>).
  </p>

  <pre class="shell">
>>> Permission.USER_READ | Permission.USER_WRITE
&lt;Permission={USER_READ,USER_WRITE}>
>>> (Permission.USER_READ | Permission.USER_WRITE) &amp; Permission.USER_WRITE
&lt;Permission=USER_WRITE>
>>> (Permission.USER_READ | Permission.USER_WRITE) ^ Permission.USER_WRITE
&lt;Permission=USER_READ>
>>>
  </pre>

  <p>The unary operator <code>~</code> (<em>not</em>) is also defined:</p>

  <pre class="shell">
>>> ~Permission.USER_READ
&lt;Permission={GROUP_EXECUTE,GROUP_READ,GROUP_WRITE,OTHER_EXECUTE,OTHER_READ,OTHER_WRITE,USER_EXECUTE,USER_WRITE}>
>>>
  </pre>

  <p>Constants created using these operators also have a <code>value</code>
  attribute.</p>

  <pre class="shell">
>>> (~Permission.USER_WRITE).value
383
>>>
  </pre>

  <p>
    Note the care taken to ensure the <code>~</code> operator is applied first
    and the <code>value</code>attribute is looked up second.
  </p>

  <p>A <code>Flags</code> subclass can also define methods, just as
  a <code>Names</code> or <code>Values</code> subclass may.  For example,
  <code>Permission</code> might benefit from a method to format a flag as a
  string in the traditional style.  Consider this addition to that class:</p>

  <pre class="python">
from twisted.python import filepath
from twisted.python.constants import FlagConstant, Flags
class Permission(Flags):
    ...

    @classmethod
    def format(cls, permissions):
        """
        Format permissions flags in the traditional 'rwxr-xr-x' style.
        """
        return filepath.Permissions(permissions.value).shorthand()
  </pre>

  <p>Use this like any other class method:</p>

  <pre class="shell">
>>> Permission.format(Permission.USER_READ | Permission.USER_WRITE | Permission.GROUP_READ | Permission.OTHER_READ)
'rw-r--r--'
>>>
  </pre>
</body>
</html>
